package com.pisolution.scheduler.datasource.instance;

import com.pisolution.scheduler.datasource.workflow.Workflow;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

import java.util.Date;

/**
 * 任务实例数据实体.
 *
 * @author sora
 * @version 0.1.0
 */
@TableName(value = "task_instance")
public class TaskInstance {
    // -------------------------------------------------------------------------------------------------
    //  数据单元 (基础信息)
    // -------------------------------------------------------------------------------------------------

    /** 任务实例标识. */
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    /** 任务节点名称. */
    @TableField(value = "name")
    private String name;

    /** 任务节点类型. */
    @TableField(value = "type")
    private String type;

    /** 任务节点优先级. */
    @TableField(value = "priority")
    private Priority priority;

    /** 任务实例完整内容 json格式. */
    @TableField(value = "content")
    private String content;

    // -------------------------------------------------------------------------------------------------
    //  数据单元 (关联信息)
    // -------------------------------------------------------------------------------------------------

    /** 所属工作流标识. */
    @TableField(value = "workflow_id")
    private int workflowId;

    /** 所属工作流. */
    @TableField(value = "workflow", exist = false)
    private Workflow workflow;

    /** 所属工作流实例标识. */
    @TableField(value = "workflow_instance_id")
    private int workflowInstanceId;

    /** 所属工作流实例. */
    @TableField(value = "workflow_instance", exist = false)
    private WorkflowInstance workflowInstance;

    /** 所属工作流实例优先级. */
    @TableField(value = "workflow_instance_priority", exist = false)
    private Priority workflowInstancePriority;

    /** 执行任务实例的用户标识. */
    @TableField(value = "user_id")
    private Integer userId;

    // -------------------------------------------------------------------------------------------------
    //  数据单元 (执行环境)
    // -------------------------------------------------------------------------------------------------

    /** 负责运行该任务实例的工作节点主机地址. */
    @TableField(value = "host")
    private String host;

    /** 运行该任务实例的工作节点所在分组. */
    @TableField(value = "worker_group")
    private String workerGroup;

    /** 运行任务实例的基础路径. */
    @TableField(value = "execute_path")
    private String executePath;

    /** 任务实例运行日志的存储路径. */
    @TableField(value = "log_path")
    private String logPath;

    /** 最大失败重试次数. */
    @TableField(value = "max_retry_count")
    private int maxRetryCount;

    /** 失败重试间隔. */
    @TableField(value = "retry_interval")
    private int retryInterval;

    // -------------------------------------------------------------------------------------------------
    //  数据单元 (运行信息)
    // -------------------------------------------------------------------------------------------------

    /** 运行该任务实例的进程号. */
    @TableField(value = "pid")
    private int pid;

    /** 任务实例运行状态. */
    @TableField(value = "state")
    private ExecutionState state;

    /** 任务实例提交时间. */
    @TableField(value = "submit_time")
    private Date submitTime;

    /** 任务实例开始运行时间. */
    @TableField(value = "start_time")
    private Date startTime;

    /** 任务实例结束运行时间. */
    @TableField(value = "end_time")
    private Date endTime;

    /** 运行时间. */
    @TableField(value = "duration", exist = false)
    private Long duration;

    /** 重试次数. */
    @TableField(value = "retry_count")
    private int retryCount;

    // -------------------------------------------------------------------------------------------------
    //  属性访问
    // -------------------------------------------------------------------------------------------------

    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getType() {
        return this.type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Priority getPriority() {
        return this.priority;
    }

    public void setPriority(Priority priority) {
        this.priority = priority;
    }

    public String getContent() {
        return this.content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public void setWorkflowId(int workflowId) {
        this.workflowId = workflowId;
    }

    public Workflow getWorkflow() {
        return this.workflow;
    }

    public int getWorkflowInstanceId() {
        return this.workflowInstanceId;
    }

    public void setWorkflowInstanceId(int workflowInstanceId) {
        this.workflowInstanceId = workflowInstanceId;
    }

    public WorkflowInstance getWorkflowInstance() {
        return this.workflowInstance;
    }

    public void setWorkflowInstance(WorkflowInstance workflowInstance) {
        this.workflowInstance = workflowInstance;
    }

    public void setWorkflowInstancePriority(Priority workflowInstancePriority) {
        this.workflowInstancePriority = workflowInstancePriority;
    }

    public Integer getUserId() {
        return this.userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getHost() {
        return this.host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public String getWorkerGroup() {
        return this.workerGroup;
    }

    public void setWorkerGroup(String workerGroup) {
        this.workerGroup = workerGroup;
    }

    public String getExecutePath() {
        return this.executePath;
    }

    public void setExecutePath(String executePath) {
        this.executePath = executePath;
    }

    public String getLogPath() {
        return this.logPath;
    }

    public void setLogPath(String logPath) {
        this.logPath = logPath;
    }

    public int getMaxRetryCount() {
        return this.maxRetryCount;
    }

    public void setMaxRetryCount(int maxRetryCount) {
        this.maxRetryCount = maxRetryCount;
    }

    public int getRetryInterval() {
        return this.retryInterval;
    }

    public void setRetryInterval(int retryInterval) {
        this.retryInterval = retryInterval;
    }

    public ExecutionState getState() {
        return this.state;
    }

    public void setState(ExecutionState state) {
        this.state = state;
    }

    public void setSubmitTime(Date submitTime) {
        this.submitTime = submitTime;
    }

    public Date getStartTime() {
        return this.startTime;
    }

    public void setStartTime(Date startTime) {
        this.startTime = startTime;
    }

    public Date getEndTime() {
        return this.endTime;
    }

    public void setEndTime(Date endTime) {
        this.endTime = endTime;
    }

    public int getRetryCount() {
        return this.retryCount;
    }

    public void setRetryCount(int retryCount) {
        this.retryCount = retryCount;
    }

    // -------------------------------------------------------------------------------------------------
    //  辅助方法
    // -------------------------------------------------------------------------------------------------

    /**
     * 确认当前任务是否已经执行完成.
     *
     * @return 如果已经执行完成 则返回 {@code true} 否则返回 {@code false}.
     */
    public boolean isTaskComplete() {
        return this.state == ExecutionState.SUCCESS
            || this.state == ExecutionState.KILL
            || this.state == ExecutionState.STOP
            || this.state == ExecutionState.PAUSE
            || this.isTaskError();
    }

    /**
     * 确认当前任务是否执行失败.
     *
     * @return 如果执行失败 则返回 {@code true} 否则返回 {@code false}.
     */
    public boolean isTaskError() {
        return this.state == ExecutionState.FAILURE || this.state == ExecutionState.NEED_FAULT_TOLERANCE && !this.canRetry();
    }

    /**
     * 确认当前任务是否可重试.
     *
     * @return 如果可以重试 则返回 {@code true} 否则返回 {@code false}.
     */
    public boolean canRetry() {
        if (this.state == ExecutionState.NEED_FAULT_TOLERANCE) {
            return true;
        }

        return this.state == ExecutionState.FAILURE && this.retryCount < this.maxRetryCount;
    }
}
